package com.ruoyi.contract.service.scheduled;

import com.ruoyi.contract.domain.Contract;
import com.ruoyi.contract.domain.ExpirationReminder;
import com.ruoyi.contract.domain.ExpirationReminderSetup;
import com.ruoyi.contract.domain.PaymentCollectionPlan;
import com.ruoyi.contract.domain.contractVo.ContractAllPaymentVo;
import com.ruoyi.contract.mapper.ExpirationReminderMapper;
import com.ruoyi.contract.mapper.ExpirationReminderSetupMapper;
import com.ruoyi.contract.service.IContractService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @program: Smart-contract-management-system-replica-system
 * @description: 合同到期提醒定时任务
 * @author: coderChen
 * @create: 2024-10-24 14:46
 **/

@Component("ContractReminderTask")
public class ContractExpirationReminderTask {

    @Autowired
    private ExpirationReminderMapper expirationReminderMapper;
    @Autowired
    private ExpirationReminderSetupMapper expirationReminderSetupMapper;
    @Autowired
    private ReminderConfiguration reminderConfiguration;
    @Autowired
    private IContractService contractService;

    final String CONTRACT_REMIND = "合同到期提醒";
    final String PAYMENT_REMIND = "到期应收款提醒";
    final String COLLECTION_REMIND = "到期应付款提醒";

    public void checkReminders() {
        System.out.println("------------------定时任务开始执行：" + LocalDateTime.now() + "----------------");
        // 加载到期提醒配置信息
        getDispostionInfo();
        System.out.println("提醒配置内容：" + reminderConfiguration.toString());
        if (reminderConfiguration.getContractRemind() == null &&
                reminderConfiguration.getPaymentRemind() == null &&
                reminderConfiguration.getCollectionRemind() == null) {
            System.out.println("------------------没有有效的提醒配置，定时任务取消执行：" + LocalDateTime.now() + "----------------");
            return;
        }
        Contract contract = new Contract();
        // 获取合同信息
        List<ContractAllPaymentVo> contractAllPaymentVoList = contractService.selectContractPaymentList(contract);
        for (ContractAllPaymentVo contractAllPaymentVo : contractAllPaymentVoList) {
            // 处理合同到期提醒
            handleContractReminder(contractAllPaymentVo);
            if ("收款".equals(contractAllPaymentVo.getContract().getCollectionAndPaymentTypes())) {
                //到期应收款
                handlePaymentPlanReminder(contractAllPaymentVo.getPaymentCollectionPlanVos(), PAYMENT_REMIND);
            } else if ("付款".equals(contractAllPaymentVo.getContract().getCollectionAndPaymentTypes())) {
                //到期应付款
                handlePaymentPlanReminder(contractAllPaymentVo.getPaymentCollectionPlanVos(), COLLECTION_REMIND);
            }
        }
        System.out.println("------------------定时任务执行完成：" + LocalDateTime.now() + "----------------");
    }

    // 处理合同到期提醒的方法
    private void handleContractReminder(ContractAllPaymentVo contractAllPaymentVo) {
        // 如果合同信息存在并且合同到期提醒被设置
        if (contractAllPaymentVo.getContract() != null && reminderConfiguration.getContractRemind() != null) {
            Contract contract = new Contract();
            BeanUtils.copyProperties(contractAllPaymentVo.getContract(), contract);
            // 检查并插入提醒信息
            checkAndInsertReminder(contract.getTerminationTime(), contract.getContractId(), CONTRACT_REMIND);
        }
    }

    // 处理收付款计划提醒的方法
    private void handlePaymentPlanReminder(List<PaymentCollectionPlan> paymentCollectionPlanVos, String reminderType) {
        if (paymentCollectionPlanVos != null) {
            for (PaymentCollectionPlan plan : paymentCollectionPlanVos) {
                // 检查state字段，如果已收款则跳过
                if ("已收款".equals(plan.getState())) {
                    continue;
                }
                if (reminderType.equals(PAYMENT_REMIND) && reminderConfiguration.getPaymentRemind() != null) {
                    // 处理到期应收款提醒的情况
                    checkAndInsertReminder(plan.getPayableTime(), plan.getContractId(), reminderType);
                }
                if (reminderType.equals(COLLECTION_REMIND) && reminderConfiguration.getCollectionRemind() != null) {
                    // 处理到期应付款提醒的情况
                    checkAndInsertReminder(plan.getPayableTime(), plan.getContractId(), reminderType);
                }
            }
        }
    }

    // 检查并插入提醒信息的方法
    private void checkAndInsertReminder(Date terminationTime, Long contractId, String reminderType) {
        if (terminationTime == null) {
            // 避免空指针异常
            System.out.println("Termination time is null for contractId: " + contractId);
            return;
        }
        // 计算当前时间与到期时间的差异天数
        long diff = calculateDaysUntilTermination(terminationTime);
        // 获取提醒配置中的7天和30天提醒时间
        String sevenAlarmTime = reminderConfiguration.getSevenAlarmTimeMap().get(reminderType);
        String thirtyAlarmTime = reminderConfiguration.getThirtyAlarmTimeMap().get(reminderType);

        // 根据配置时间检查并插入7天和30天的提醒
        insertReminderIfApplicable(diff, contractId, reminderType, sevenAlarmTime, 7L);
        insertReminderIfApplicable(diff, contractId, reminderType, thirtyAlarmTime, 30L);
    }

    // 根据条件检查并插入提醒信息的方法
    private void insertReminderIfApplicable(long diff, Long contractId, String reminderType, String alarmTime, Long maturityDays) {
        // 如果设置了提前7天提醒并且距离截止还有7天
        if ("7".equals(alarmTime) && diff == maturityDays) {
            insertReminder(contractId, maturityDays, reminderType);
        }
        // 如果设置了提前30天提醒并且距离截止还有30天
        else if ("30".equals(alarmTime) && diff == maturityDays) {
            insertReminder(contractId, maturityDays, reminderType);
        }
    }

    // 插入到期提醒信息的方法
    private void insertReminder(Long contractId, Long maturityDays, String alarmType) {
        ExpirationReminder expirationReminder = new ExpirationReminder();
        expirationReminder.setContractId(contractId);
        expirationReminder.setMaturityDays(maturityDays);
        expirationReminder.setState("未到期");
        expirationReminder.setAlarmType(alarmType);
        expirationReminder.setCreateTime(new Date());
        // 新增到期提醒信息到数据库
        expirationReminderMapper.insertExpirationReminder(expirationReminder);
    }

public void getDispostionInfo() {
    List<ExpirationReminderSetup> configInfoList = expirationReminderSetupMapper.selectReminderSetupInfo();
    boolean hasActiveConfig = false;
    // 设置所有提醒类型为 null，防止没有任何配置生效时，存在残留的提醒时间
    reminderConfiguration.setContractRemind(null);
    reminderConfiguration.setPaymentRemind(null);
    reminderConfiguration.setCollectionRemind(null);
    for (ExpirationReminderSetup configInfo : configInfoList) {
        // 获取提醒配置
        String type = configInfo.getType();
        String state = configInfo.getState();
        String alarmTime = configInfo.getAlarmTime();
        if ("1".equals(state)) {
            // 配置生效时，更新提醒类型
            hasActiveConfig = true;
            switch (type) {
                case "合同到期提醒":
                    reminderConfiguration.setContractRemind(type);
                    break;
                case "到期应付款提醒":
                    reminderConfiguration.setPaymentRemind(type);
                    break;
                case "到期应收款提醒":
                    reminderConfiguration.setCollectionRemind(type);
                    break;
            }
            // 分割并处理提醒时间
            String[] alarmTimes = alarmTime.split(",");
            processAlarmTimes(type, alarmTimes);
        } else {
            // 如果状态不为 "1"，设置该提醒时间为 null
            switch (type) {
                case "合同到期提醒":
                    reminderConfiguration.setContractRemind(null);
                    break;
                case "到期应付款提醒":
                    reminderConfiguration.setPaymentRemind(null);
                    break;
                case "到期应收款提醒":
                    reminderConfiguration.setCollectionRemind(null);
                    break;
            }
        }
    }

    // 如果没有任何配置生效，则将 reminderConfiguration 的所有提醒类型置为 null
    if (!hasActiveConfig) {
        reminderConfiguration.setContractRemind(null);
        reminderConfiguration.setPaymentRemind(null);
        reminderConfiguration.setCollectionRemind(null);
    }
}

    private void processAlarmTimes(String type, String[] alarmTimes) {
        for (String time : alarmTimes) {
            switch (time.trim()) {
                case "7":
                    reminderConfiguration.setSevenAlarmTime(type, time);
                    break;
                case "30":
                    reminderConfiguration.setThirtyAlarmTime(type, time);
                    break;
                default:
                    break;
            }
        }
    }


    /**
     * 计算当前日期与合同终止日期之间的天数差异，不精确到时分秒。
     *
     * @param terminationTime 合同终止日期
     * @return 返回天数差异
     */
    private static long calculateDaysUntilTermination(Date terminationTime) {
        // 获取当前日期，不包含时分秒
        LocalDate today = LocalDate.now();
        // 将terminationTime转换为LocalDate
        LocalDate terminationDate = terminationTime.toInstant()
                .atZone(ZoneId.systemDefault())
                .toLocalDate();
        // 计算两个日期之间的天数差
        return ChronoUnit.DAYS.between(today, terminationDate);
    }

}